package com.hy.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hy.common.Result;
import com.hy.dto.user.UserDTO;
import com.hy.dto.wechatDto.WechatLoginDto;
import com.hy.entity.User;
import com.hy.entity.vo.GenderStatisticsVO;
import com.hy.entity.vo.UserVO;
import com.hy.exception.BusinessException;
import com.hy.mapper.UserMapper;
import com.hy.service.UserService;
import com.hy.util.JwtUtil;
import com.hy.util.UserExcelListener;
import com.hy.util.WechatUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private WechatUtil wechatUtil;
    @Autowired
    private UserMapper userMapper;

    @Override
    @Transactional
    public boolean reducePoints(Long userId, Integer points) {
        return baseMapper.reducePoints(userId, points) > 0;
    }

    @Override
    @Transactional
    public boolean addPoints(Long userId, Integer points) {
        User user = getById(userId);
        if (user == null) {
            return false;
        }
        user.setPoints(user.getPoints() + points);
        return updateById(user);
    }

    @Override
    public User getByOpenid(String openid) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getOpenid, openid);
        return getOne(wrapper);
    }

    @Override
    public Map<String, Object> weChatLogin(WechatLoginDto request) {

        // 通过code获取openid
        String openid = wechatUtil.getOpenid(request.getCode());

        // 根据openid查询用户
        User user = getByOpenid(openid);

        // 如果用户不存在，则自动注册
        if (user == null) {
            user = new User();
            user.setOpenid(openid);
            user.setPoints(0);
            save(user);
        }

        // 生成token
        String token = jwtUtil.generateToken(openid, user.getId());

        // 返回用户信息和token
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("user", user);
        return map;
    }

    @Override
    public void exportMemberTemplate(HttpServletResponse response) throws IOException {
        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");

        // 防止中文乱码
        String fileName = URLEncoder.encode("会员导入模板.xlsx", String.valueOf(StandardCharsets.UTF_8));
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);

        // 创建表头数据（空列表，仅导出表头）
        List<User> templateData = new ArrayList<>();

        // 导出Excel
        EasyExcel.write(response.getOutputStream(), User.class)
                .sheet("会员信息")
                .doWrite(templateData);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importMembers(MultipartFile file) throws Exception {
        if (file.isEmpty()) {
            throw new BusinessException(400, "上传文件不能为空");
        }

        UserExcelListener listener = new UserExcelListener();
        EasyExcel.read(file.getInputStream(), User.class, listener).sheet().doRead();

        List<User> users = listener.getUserList();
        if (CollectionUtils.isEmpty(users)) {
            throw new BusinessException(400, "Excel中未包含会员数据");
        }

        // 数据预处理
        LocalDateTime now = LocalDateTime.now();
        users.forEach(user -> {
            user.setCreateTime(now);
            user.setUpdateTime(now);
            // 可添加其他业务校验逻辑
        });

        // 批量保存
        saveBatch(users);
    }

    @Override
    public void addMember(UserDTO userDTO) {
        // 参数校验
        validateUserDTO(userDTO);

        User user = new User();
        BeanUtils.copyProperties(userDTO, user);

        // 设置默认值
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        if (user.getPoints() == null) {
            user.setPoints(0);
        }

        // 保存数据
        if (!save(user)) {
            throw new BusinessException(500, "添加会员失败");
        }
    }

    @Override
    public void deleteMember(Integer id) {
        if (id == null) {
            throw new BusinessException(400, "会员ID不能为空");
        }

        // 检查会员是否存在
        User user = getById(id);
        if (user == null) {
            throw new BusinessException(404, "会员不存在");
        }

        // 执行删除（逻辑删除或物理删除）
        if (!removeById(id)) {
            throw new BusinessException(500, "删除会员失败");
        }
    }

    @Override
    public void updateMember(UserDTO userDTO) {
        if (userDTO.getId() == null) {
            throw new BusinessException(400, "会员ID不能为空");
        }

        // 检查会员是否存在
        User existUser = getById(userDTO.getId());
        if (existUser == null) {
            throw new BusinessException(404, "会员不存在");
        }

        // 复制属性（忽略空值）
        BeanUtils.copyProperties(userDTO, existUser, getNullPropertyNames(userDTO));

        // 更新时间
        existUser.setUpdateTime(LocalDateTime.now());

        // 执行更新
        if (!updateById(existUser)) {
            throw new BusinessException(500, "更新会员失败");
        }
    }

    @Override
    public UserVO getMemberById(Integer id) {
        if (id == null) {
            throw new BusinessException(400, "会员ID不能为空");
        }

        User user = getById(id);
        if (user == null) {
            throw new BusinessException(404, "会员不存在");
        }

        // 转换为VO
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }

    @Override
    public Page<UserVO> listMembers(Integer pageNum, Integer pageSize, String name, String phone) {
        // 构建查询条件
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(name)) {
            queryWrapper.like("name", name);
        }
        if (StringUtils.isNotBlank(phone)) {
            queryWrapper.like("phone", phone);
        }

        // 分页查询
        Page<User> page = page(new Page<>(pageNum, pageSize), queryWrapper);

        // 转换为VO列表
        List<UserVO> userVOList = page.getRecords().stream()
                .map(user -> {
                    UserVO vo = new UserVO();
                    BeanUtils.copyProperties(user, vo);
                    return vo;
                })
                .collect(Collectors.toList());

        // 构建返回结果
        Page<UserVO> resultPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        resultPage.setRecords(userVOList);
        return resultPage;
    }

    @Override
    public GenderStatisticsVO getGenderStatistics() {
        return userMapper.getGenderStatistics();
    }

    @Override
    public List<User> getAllUsers() {
        return this.list();
    }

    //修改当前登录用户信息
    @Override
    public Result<User> updateUserinfo(User user) {
        if (user == null) {
            return Result.error("用户信息不能为空");
        }
        try {
            userMapper.updateById(user);
            return Result.success("修改成功!");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("修改失败");
        }
    }


    // 参数校验方法
    private void validateUserDTO(UserDTO userDTO) {
        if (userDTO == null) {
            throw new BusinessException(400, "会员信息不能为空");
        }

        if (StringUtils.isBlank(userDTO.getName())) {
            throw new BusinessException(400, "姓名不能为空");
        }

        if (StringUtils.isBlank(userDTO.getPhone())) {
            throw new BusinessException(400, "手机号不能为空");
        }

        // 可添加更多校验逻辑
    }

    // 获取对象中为null的属性名
    private String[] getNullPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<>();
        for (java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) emptyNames.add(pd.getName());
        }

        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }
}
